<?
if (!defined('SMF'))
	die('Hacking attempt...');

/******************************************************************
* Explanation of the scheduler                                    *
*                                                                 *
* Here are the scheduler DB fields, and what they are used for :  *
*  - sched_id : Unique ID. Before calling the file responsible    *
*    for the event, the variable $sched_var_id will be set to     *
*    this value, so the called file can modify the triggering     *
*    scheduler entry if it needs to.                              *
*                                                                 *
*  - repeate : Set this to 'Y' if you want the event to be        *
*    repeated endlessly. If this value is set to 'Y', the 'spawn' *
*    field is not used.                                           *
*                                                                 *
*  - ticks_left : Used internally by the scheduler. It represents *
*    the number of mins elapsed since the last call. ALWAYS set   *
*    this to 0 when scheduling a new event.                       *
*                                                                 *
*  - ticks_full : This is the interval in minutes between         *
*    different runs of your event. Set this to the frenquency     *
*    you wish the event to happen. For example, if you want your  *
*    event to be run every three minutes, set this to 3.          *
*                                                                 *
*  - spawn : If you want your event to be run a certain number of *
*    times only, set this to the number of times. For this to     *
*    work, loop must be set to 'N'. When the event has been run   *
*    spawn number of times, it is deleted from the scheduler.     *
*                                                                 *
*  - sched_file : This is the file that will be called when an    *
*    event has been trigerred.                                    *
*                                                                 *
*  - extra_info : This is a text variable that can be used to     *
*    store any extra information concerning the event triggered.  *
*    It will be made available to the called file through the     *
*    variable $sched_var_extrainfo.                               *
*                                                                 *
* If you are including files in your trigger file, it is important*
* to use include_once() instead of include(), as your file might  *
* be called multiple times in a single execution. If you need to  *
* define functions, you can put them in the sched_funcs.php file  *
* that is included by the scheduler. Else put them in your own    *
* include file, with an include statement. THEY CANNOT BE         *
* DEFINED IN YOUR MAIN FILE BODY. This would cause PHP to issue a *
* multiple function declaration error.                            *
*                                                                 *
******************************************************************/
global $smcFunc, $txt, $scripturl, $boarddir, $user_info;
global $dbtables, $sched_ticks, $admin_mail;

// Pull the scheduler information
$sched_res = $smcFunc['db_query']('', '
	SELECT *
	FROM {raw:db_scheduler}',
	array(
		'db_scheduler' => $dbtables['scheduler']
	)
);

// Check to make sure this has not been called already.
$row = $smcFunc['db_fetch_assoc']($sched_res);
if ($row['next_run'] > time())
{
	include($boarddir . "/bnt/footer.php");
	die();
}


// Update last_run to ensure no one else kicks off a scheduler run
$nextrun = ($sched_ticks * 60) + time();
$update = $smcFunc['db_query']('', '
	UPDATE {raw:db_scheduler}
	SET next_run = {float:time}',
	array(
		'db_scheduler' => $dbtables['scheduler'],
		'time' => $nextrun
	)
);

// Reset data pointer to the beginning of the scheduler result
$smcFunc['db_data_seek'] ($sched_res, 0);

$message = '<html><body>';

$message .= '<p>Last Run: ' . $row['next_run'] . '</p>';
$message .= '<p>Next Run: ' . $nextrun . '</p>';

srand((double)microtime() * 1000000);

$starttime = time();

if ($smcFunc['db_num_rows']($sched_res) > 0)
{
	while ($event = $smcFunc['db_fetch_assoc']($sched_res))
	{
		$message .= '<h3>Running ' . $event['sched_file'] . '</h3>';
		
		
		// Get the base multiplier assuming the function has been executed on schedule
		$multiplier = ($sched_ticks / $event['ticks_full']) + ($event['ticks_left'] / $event['ticks_full']);
		$multiplier = intval($multiplier);
		
		$message .= '<p>Base multiplier: ' . $multiplier . '</p>';
		
		// Check to see if the function has not been executed inside the defined schedule as set by sched_ticks.
		//
		// If the difference between the the scheduler start time and the last run time of the function 
		// is greater the scheduled interval + 60 seconds then increase the multiplier accordingly.
		//
		// The scheduler works only in increments of whole minutes, so scheduled interval + 60 should cover
		// any potentially missed events.
		
		$difference = $starttime - ($event['next_run'] - ($sched_ticks * 60));
		$message .= '<p>Time difference for ' . $event['sched_file'] . ': ' . $difference . '</p>';

		if ($difference >= ($sched_ticks * 60 + 60))
		{
			$missed_ticks = intval(($difference - $sched_ticks * 60) / 60);
			$message .= '<p> Missing ticks: ' . $missed_ticks . '</p>';
			$missed_multiplier = ($missed_ticks / $event['ticks_full']);
			$message .= '<p> Multiplier adder: ' . intval($missed_multiplier) . '</p>';
			$multiplier += intval($missed_multiplier);
			$message .= '<p> Updated multiplier: ' . $multiplier . '</p>';
		}
		
		$ticks_left = ($sched_ticks + $event['ticks_left']) % $event['ticks_full'];

		if ($event['repeate'] == 'N')
		{
			if ($multiplier > $event['spawn'])
				$multiplier = $event['spawn'];

			if ($event['spawn'] - $multiplier == 0)
			{
				$delete = $smcFunc['db_query']('', '
					DELETE FROM {raw:db_scheduler}
					WHERE sched_id = {int:sched_id}',
					array(
						'db_scheduler' => $dbtables['scheduler'],
						'sched_id' => $event['sched_id']
					)
				);
			}
			else
			{
				$update = $smcFunc['db_query']('', '
					UPDATE {raw:db_scheduler}
					SET ticks_left = {int:ticks_left}.
						spawn = spawn - {int:multiplier}
					WHERE sched_id = {int:sched_id}',
					array(
						'db_scheduler' => $dbtables['scheduler'],
						'ticks_left' => $ticks_left,
						'multiplier' => $multiplier,
						'sched_id' => $event['sched_id']
					)
				);
			}
		}
		else
		{
			$update = $smcFunc['db_query']('', '
				UPDATE {raw:db_scheduler}
				SET ticks_left = {int:ticks_left}
				WHERE sched_id = {int:sched_id}',
				array(
					'db_scheduler' => $dbtables['scheduler'],
					'ticks_left' => $ticks_left,
					'sched_id' => $event['sched_id']
				)
			);
		}
		$sched_var_id = $event['sched_id'];
		$sched_var_extrainfo = $event['extra_info'];
		
		if ($multiplier > 0)
			include($boarddir . '/bnt/' . $event['sched_file']);
	}
}

$smcFunc['db_free_result']($sched_res);

$runtime = time() - $starttime;
$message .= '<p>The scheduler took ' . $runtime . ' seconds to execute.</p>';

// Send status email
$to       = $admin_mail;
$subject  = "Scheduler Status";
$message .= "</body></html>";
$headers  = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1\r\n";

//mail($to, $subject, $message, $headers);

// Pull player info into $playerinfo.
$result = $smcFunc['db_query']('', '
	SELECT *
	FROM {raw:db_ships}
	WHERE user_id = {int:user_id}',
	array(
		'db_ships' => $dbtables['ships'],
		'user_id' => $user_info['id'],
	)
);
$playerinfo = $smcFunc['db_fetch_assoc']($result);
$smcFunc['db_free_result']($result);

// Update player's last online status
$update = $smcFunc['db_query']('', '
	UPDATE {raw:db_ships}
	SET last_login = NOW()
	WHERE ship_id = {int:ship_id}',
	array(
		'db_ships' => $dbtables['ships'],
		'ship_id' => $playerinfo['ship_id'],
	)
);

// Write turns available for JS to pickup and update display
echo '<input id="scheduler_turns_available" type="hidden" value="', Number($playerinfo['turns']), '" />';

include($boarddir . "/bnt/footer.php");
?>